home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / PROGTOOL / PASSDK30.ZIP;1 / DISK1.ZIP / PAS / SUBS / MIXERS / FYI / MIXERS.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-12-01  |  45.2 KB  |  1,756 lines

  1. ;$Author:   DCODY  $
  2. ;$Date:   01 Dec 1992 11:18:02  $
  3. ;$Header:   X:/sccs/mixers/mixers.asv   1.4   01 Dec 1992 11:18:02   DCODY  $
  4. ;$Log:   X:/sccs/mixers/mixers.asv  $
  5. ;  
  6. ;     Rev 1.4   01 Dec 1992 11:18:02   DCODY
  7. ;  corrected a misnamed register. Changed the code to support revD
  8. ;  mv508 mixer problem
  9. ;  
  10. ;     Rev 1.3   24 Nov 1992 12:04:46   DCODY
  11. ;  renamed the 510 table to 508 table
  12. ;  
  13. ;     Rev 1.2   28 Jun 1992 11:36:42   DCODY
  14. ;  fixed FM split, and made SB channel assigment changes on entry to SETMIXER
  15. ;  
  16. ;     Rev 1.1   23 Jun 1992 16:45:28   DCODY
  17. ;  PAS2 update
  18. ;  
  19. ;     Rev 1.0   15 Jun 1992 09:41:36   BCRANE
  20. ;  Initial revision.
  21. ;$Logfile:   X:/sccs/mixers/mixers.asv  $
  22. ;$Modtimes$
  23. ;$Revision:   1.4  $
  24.  
  25.     Title    MIXERS    --  Games Authors interface to MIXER/VOLUME/CROSS/FILTER
  26.     page    64,131
  27.  
  28. ;   /*\
  29. ;---|*|----====< MIXERS >====----
  30. ;---|*|
  31. ;---|*|  This module contains the code for supporting the mixers,filter,
  32. ;---|*|  volume control, and PCM I/O.
  33. ;---|*|
  34. ;   |*|  Media Vision, Inc. Copyright (c) 1991, All Rights Reserved
  35. ;---|*|
  36. ;   \*/
  37. ;
  38. if1
  39.   %out      ***********************************************************
  40.   %out       *                                                         *
  41.   %out       *        ----====< Programming Caveat >====----           *
  42.   %out       *                                                         *
  43.   %out       * This code is provided as documentation ONLY. Attempting *
  44.   %out       * to use this in your program will make you hardware      *
  45.   %out       * dependent!!!. Please use the identical API located in   *
  46.   %out       * in MVHxLIB for mixer control. Here are the library      *
  47.   %out       * function names:                                         *
  48.   %out       *                                                         *
  49.   %out       *     int (far *MVSetMixerFunction)  ();                  *
  50.   %out       *     int (far *MVSetVolumeFunction) ();                  *
  51.   %out       *     int (far *MVSetFilterFunction) ();                  *
  52.   %out       *     int (far *MVSetCrossChannel)   ();                  *
  53.   %out       *     int (far *MVGetMixerFunction)  ();                  *
  54.   %out       *     int (far *MVGetVolumeFunction) ();                  *
  55.   %out       *     int (far *MVGetFilterFunction) ();                  *
  56.   %out       *     int (far *MVGetCrossChannel)   ();                  *
  57.   %out       *     int (far *MVRealSoundSwitch)   ();                  *
  58.   %out       *     int (far *MVFMSplitSwitch)     ();                  *
  59.   %out       *                                                         *
  60.   %out       ***********************************************************
  61.         .err
  62. endif
  63.  
  64. ;
  65. ;   /*\
  66. ;---|*|
  67. ;---|*|----=======================================================---------
  68. ;---|*|----====< MVSOUND.SYS function table entry conditions:
  69. ;---|*|----=======================================================---------
  70. ;---|*|
  71. ;---|*| This function returns a segment:offset to the table of 10 functions
  72. ;---|*| The table is made up of 32 bit pointers to the ten far routines.
  73. ;---|*| Each routine has different register requirements:
  74. ;---|*|
  75. ;---|*|  Function #1 Set a Mixer.
  76. ;---|*|
  77. ;---|*|         Entry Condition:
  78. ;---|*|         BX is the setting      (0% - 100%)
  79. ;---|*|         CX is the mixer select (BI_OUTPUTMIXER | BI_INPUTMIXER)
  80. ;---|*|         DX is the channel      (ex: BI_L_FM, BI_R_FM, etc.)
  81. ;---|*|
  82. ;---|*|         Exit Condition:
  83. ;---|*|         All other registers are unchanged.
  84. ;---|*|
  85. ;---|*|  Function #2 Set the Volume/Equalizer device.
  86. ;---|*|
  87. ;---|*|         Entry Condition:
  88. ;---|*|         BX is the setting      (0% - 100%)
  89. ;---|*|         CX is the volume channel select:
  90. ;---|*|
  91. ;---|*|             BI_VOLLOUD
  92. ;---|*|             BI_VOLENHANCE
  93. ;---|*|             BI_VOLBASS
  94. ;---|*|             BI_VOLTREBLE
  95. ;---|*|             BI_VOLLEFT
  96. ;---|*|             BI_VOLRIGHT
  97. ;---|*|
  98. ;---|*|         Since some of the devices are swithes, a 0% turns it
  99. ;---|*|         off, and a 100% turns it on. The switches are:
  100. ;---|*|
  101. ;---|*|             BI_VOLLOUD      --  ENHANCED STEREO switch
  102. ;---|*|             BI_VOLENHANCE --  LOUDNESS switch
  103. ;---|*|
  104. ;---|*|         Exit Condition:
  105. ;---|*|         All other registers are unchanged.
  106. ;---|*|
  107. ;---|*|  Function #3 Set the Filter.
  108. ;---|*|
  109. ;---|*|         Entry Condition:
  110. ;---|*|         BX is a new setting    (0% - 100%)
  111. ;---|*|
  112. ;---|*|         0% filters out anything higher than 0k hz (is mute)
  113. ;---|*|           100% filters out anything higher than 20 khz
  114. ;---|*|
  115. ;---|*|         Exit Condition:
  116. ;---|*|         All other registers are unchanged.
  117. ;---|*|
  118. ;---|*|  Function #4 Set the Cross Channel.
  119. ;---|*|
  120. ;---|*|         Entry Condition:
  121. ;---|*|         BX holds the new cross channel mask bits:
  122. ;---|*|
  123. ;---|*|            00000001b Right to Right
  124. ;---|*|            00000010b Left  to Right
  125. ;---|*|            00000100b Right to Left
  126. ;---|*|            00001000b Left  to Left
  127. ;---|*|
  128. ;---|*|            A set bit turns ON the connection.
  129. ;---|*|            A clear bit turns OFF the connection.
  130. ;---|*|
  131. ;---|*|         Exit Condition:
  132. ;---|*|         All other registers are unchanged.
  133. ;---|*|
  134. ;---|*|  Function #5 Get a Mixer setting.
  135. ;---|*|
  136. ;---|*|         Entry Condition:
  137. ;---|*|         CX is the mixer select (BI_OUTPUTMIXER | BI_INPUTMIXER)
  138. ;---|*|         DX is the channel      (ex: BI_L_FM, BI_R_FM, etc.)
  139. ;---|*|
  140. ;---|*|         Exit Condition:
  141. ;---|*|         BL is the setting      (0% - 100%)
  142. ;---|*|         BH is 0 for off, FF for on.
  143. ;---|*|         All other registers are unchanged.
  144. ;---|*|
  145. ;---|*|  Function #6 Get the Volume/Equalizer setting.
  146. ;---|*|
  147. ;---|*|         Entry Condition:
  148. ;---|*|         CX is the volume channel select:
  149. ;---|*|
  150. ;---|*|             BI_VOLLOUD
  151. ;---|*|             BI_VOLENHANCE
  152. ;---|*|             BI_VOLBASS
  153. ;---|*|             BI_VOLTREBLE
  154. ;---|*|             BI_VOLLEFT
  155. ;---|*|             BI_VOLRIGHT
  156. ;---|*|                     BI_VOLMODE
  157. ;---|*|
  158. ;---|*|         Since some of the devices are swithes, a 0% turns it
  159. ;---|*|         off, and a 100% turns it on. The switches are:
  160. ;---|*|
  161. ;---|*|             BI_VOLLOUD      --  ENHANCED STEREO switch
  162. ;---|*|             BI_VOLENHANCE --  LOUDNESS switch
  163. ;---|*|
  164. ;---|*|         Exit Condition:
  165. ;---|*|         BX is the setting      (0% - 100%)
  166. ;---|*|         All other registers are unchanged.
  167. ;---|*|
  168. ;---|*|  Function #7 Get the Filter setting.
  169. ;---|*|
  170. ;---|*|         Entry Condition:
  171. ;---|*|           None
  172. ;---|*|
  173. ;---|*|         Exit Condition:
  174. ;---|*|         BX is a new setting    (0% - 100%)
  175. ;---|*|         0% filters out anything higher than 0k hz (is mute)
  176. ;---|*|           100% filters out anything higher than 20 khz
  177. ;---|*|
  178. ;---|*|           All other registers are unchanged.
  179. ;---|*|
  180. ;---|*|  Function #8 Get the Cross Channel setting
  181. ;---|*|
  182. ;---|*|         Entry Condition:
  183. ;---|*|         None
  184. ;---|*|
  185. ;---|*|         Exit Condition:
  186. ;---|*|         BX holds the new cross channel mask bits:
  187. ;---|*|
  188. ;---|*|            00000001b Right to Right
  189. ;---|*|            00000010b Left  to Right
  190. ;---|*|            00000100b Right to Left
  191. ;---|*|            00001000b Left  to Left
  192. ;---|*|
  193. ;---|*|            A set bit turns ON the connection.
  194. ;---|*|            A clear bit turns OFF the connection.
  195. ;---|*|
  196. ;---|*|         All other registers are unchanged.
  197. ;---|*|
  198. ;---|*|  Function #9 Get/Set the Real Sound bit.
  199. ;---|*|
  200. ;---|*|         Entry Condition:
  201. ;---|*|         BX may hold 0 to turn off realsound, 100 to turn it on.
  202. ;---|*|         CX determines if the switch is read or written. If cx
  203. ;---|*|            is 0, the switch is read. If cx is not zero, the
  204. ;---|*|            switch is written.
  205. ;---|*|
  206. ;---|*|         Exit Condition:
  207. ;---|*|         If the switch is read, BX holds 0 for off, 100 for on.
  208. ;---|*|         All other registers are unchanged.
  209. ;---|*|
  210. ;---|*|  Function #10 Get/Set the Split FM chips bit.
  211. ;---|*|
  212. ;---|*|         Entry Condition:
  213. ;---|*|         BX may hold 0 to split the chips, 100 to have mono chips
  214. ;---|*|         CX determines if the switch is read or written. If cx
  215. ;---|*|            is 0, the switch is read. If cx is not zero, the
  216. ;---|*|            switch is written.
  217. ;---|*|
  218. ;---|*|         Exit Condition:
  219. ;---|*|         If the switch is read, BX holds 0 for split, 100 for mono.
  220. ;---|*|         All other registers are unchanged.
  221. ;---|*|
  222. ;   \*/
  223.  
  224. ;
  225. ; The following equate sets up the compiled model size for this code:
  226. ;
  227.     MODELSIZE equ 0
  228.  
  229.         include model.inc
  230.         include masm.inc                ; masm equates, etc
  231.         include common.inc              ; hardware equates module
  232.     include state.inc        ; state table
  233.     include binary.inc        ; int2f binary interface module
  234.  
  235.         .code
  236.         assume ds:@code
  237.     assume es:@code
  238.  
  239. ;
  240. ; The following address is the entrypoint into the static mixer driver.
  241. ; This driver was provided as the static linked mixer driver embedded in
  242. ; MIXERC.C. This code compiles into a .COM format, then is translated into
  243. ; a header file to be included into MIXERC.C.
  244. ;
  245.     org    0h            ; The original driver worked
  246.                     ; with a zero offset.
  247.     public    StartingAddress     ; The driver was initialized by
  248. StartingAddress label    far        ; a far call to offset 0 of the driver.
  249.  
  250.     jmp    near ptr doinit     ; go do it...
  251.  
  252.         db    0        ; filler to align on next dword
  253.  
  254. signature    db    "MVPROAS01"     ; 8 byte signature
  255.  
  256.  
  257. ;   /*\
  258. ;---|*|--------------------====< Data Section >====--------------------
  259. ;   \*/
  260.  
  261. FunctionTable    label    near
  262. smixerfunc     dd    offset dosetmixer  ; set the mixers
  263. svolumefunc     dd    offset dosetvolume ; set the volume
  264. sfilterfunc     dd    offset dosetfilter ; set the filter
  265. scrossfunc     dd    offset dosetcross  ; set the cross channel
  266. gmixerfunc     dd    offset dogetmixer  ; get the mixers
  267. gvolumefunc     dd    offset dogetvolume ; get the volume
  268. gfilterfunc     dd    offset dogetfilter ; get the filter
  269. gcrossfunc     dd    offset dogetcross  ; get the cross channel
  270. realsound     dd    offset dorealsound ; get/set the realsound bit
  271. fmsplit      dd    offset dofmsplit   ; get/set the FM split bit
  272.  
  273. TheDMAChannel     db    DEFAULTDMA    ; default DMA channel
  274. TheIRQChannel     db    DEFAULTIRQ    ; default IRQ channel
  275.  
  276. ;
  277. ; These variable hold the current mixer hardware state
  278. ;
  279. _inmixertbl    dw    16 dup(0f0fh)    ; input mixer indexes, settings
  280. _outmixertbl    dw    16 dup(0f0fh)    ; output mixer indexes, settings
  281. _currmixer    db    16 dup(0fh)    ; pointer to the other tables
  282. _voltbl     dw    8  dup(000fh)    ; total volume indexes, settings
  283. _filtidx    db    0        ; filter index (0 - 6)
  284.  
  285. HardwareShadowTable    MVState <0>
  286. mvhwShadowPointer    dd    0    ; far pointer to the state table
  287. mvhwFunctionTable    dd    0    ; far pointer to the function table
  288.  
  289. HardwareType    dw    0          ; hardware feature bits
  290. ORIGPAS     equ    0000000000000000b ; all feature bits are zero
  291. bMVA508     equ    0000000000000001b ; new mixer chip
  292. CDPC        equ    0000000100000000b ; CDPC  installed at original address
  293. PAS16        equ    0000001000000000b ; PAS16 installed at original address
  294. PAS8        equ    0000010000000000b ; PAS8  installed at original address
  295.  
  296. sbleft        db    0        ; SB left mixer connection
  297. sbright     db    0        ; SB right mixer connection
  298.  
  299. ;
  300. ; a table of maximum physical settings for each of the volume control device.
  301. ;
  302. _voltblmax      db      02
  303.         db    03
  304.         db    EQUALIZERMAX
  305.         db    EQUALIZERMAX
  306. _volleftmax    db    ?        ; volume max changes between
  307. _volritmax    db    ?        ; mixer chips
  308.         db    06
  309.         db    00
  310. ;
  311. ; a linear table of filter values - from mute to high for the 8 bit filter
  312. ;
  313. tableof label    byte
  314.     db     000000b            ; mute - goes to PC speaker
  315.     db     100100b            ; 20hz to  2.9khz
  316.     db     111001b            ; 20hz to  5.9khz
  317.     db     110001b            ; 20hz to  8.9khz
  318.     db     101001b            ; 20hz to 11.9khz
  319.     db     100010b            ; 20hz to 15.9khz
  320.     db     100001b            ; 20hz to 17.8khz
  321.  
  322. ;
  323. ; National Semi's Mixer Volume settings (0 - 12)
  324. ;
  325. mixersettings    label    byte
  326.     db    0            ; level 0
  327.     db    20H            ; level 1
  328.     db    10H            ; level 2
  329.     db    08H            ; level 3
  330.     db    04H            ; level 4
  331.     db    02H            ; level 5
  332.     db    12H            ; level 6
  333.     db    2AH            ; level 7
  334.     db    16H            ; level 8
  335.     db    01H            ; level 9
  336.     db    29H            ; level A
  337.     db    1DH            ; level B
  338.     db    2FH            ; level C
  339.  
  340.  
  341. ;   /*\
  342. ;---|*|--------------------====< Code Section >====--------------------
  343. ;   \*/
  344.  
  345. ;   /*\
  346. ;---|*|------------------------==================-------------------------
  347. ;---|*|------------------------====< doinit >====-------------------------
  348. ;---|*|------------------------==================-------------------------
  349. ;---|*|
  350. ;---|*| This routine is only called if the DOS driver is not loaded, so
  351. ;---|*| we must init the various stuff...
  352. ;---|*|
  353. ;---|*| Entry Conditions:
  354. ;---|*|     None
  355. ;---|*|
  356. ;---|*| Exit Conditions:
  357. ;---|*|     DX:AX point to the function table
  358. ;---|*|     BX holds the DMA channel #
  359. ;---|*|     CX holds the IRQ channel #
  360. ;---|*|
  361. ;   \*/
  362.  
  363. invmso_done    db    0        ; perform this code just once!
  364.  
  365.     public    doinit
  366. doinit  proc    far
  367.     push    ds
  368.  
  369.         push    cs                      ; all data is stored locally.
  370.     pop    ds
  371. ;
  372. ; perform the hardware code initialization
  373. ; this code can only be processed once
  374. ;
  375.     cmp    [invmso_done],0     ; have we been here?
  376.     jjnz    inmv_done        ; yes, don't do this again
  377.     inc    [invmso_done]        ; no, so pass by just once
  378. ;
  379. ; determine the hardware and setup for default stand-alone operation
  380. ;
  381.         mov     bx,ORIGPAS              ; bx holds the flags
  382.  
  383.         mov     dx,INTRCTLR             ; check the board rev bits
  384.     in    al,dx
  385.     test    al,fICrevbits        ; non-zero means we have new hardware
  386.     jz    foundthehardware
  387.  
  388.     mov    bx,CDPC
  389.     mov    dx,MASTERMODRD        ; check for the CDPC
  390.     in    al,dx
  391.     test    al,bMMRDmsmd        ; master/slave bit set?
  392.     jnz    foundthehardware
  393.  
  394.     mov    bx,PAS8         ; check for the 8 bit card
  395.     mov    dx,SLAVEMODRD        ; check for the CDPC
  396.     in    al,dx
  397.     test    al,bSMRDdactyp        ; 16 bit DAC?
  398.     jz    foundthehardware    ; no, so it's the PAS16 card
  399.     mov    bx,PAS16+bMVA508    ; check for the 8 bit card
  400.     ;
  401.     foundthehardware:
  402.     mov    [HardwareType],bx    ; save the type
  403.  
  404.     test    bx,PAS16        ; is a PAS16 with the new mixer?
  405.  
  406.         mov     bl,MVVOLUMEMAX          ; (default to new mixer)
  407.     mov    ax,(L_FREE*256)+R_FREE    ; SB is FREE for mva508 types
  408.  
  409.         jnz     @F
  410.  
  411.         mov     bl,NSVOLUMEMAX                  ; no, use the NS mixer data
  412.     mov    ax,(L_SPEAKER*256)+R_SPEAKER    ; SB is SPEAKER for others
  413.     ;
  414.     @@:
  415.     mov    [_volleftmax],bl    ; save the maximum volume setting
  416.     mov    [_volritmax],bl
  417.     mov    [sbleft],ah        ; save the sb connections
  418.     mov    [sbright],al
  419. ;
  420. ; we must complete the 32 bit addresses in the vector table
  421. ;
  422.     push    es
  423.     push    di
  424.  
  425.     mov    ax,cs            ; ax holds the segment for storing
  426.     lea    bx,FunctionTable
  427.     mov    wptr [mvhwFunctionTable+0],bx ; save a copy of the table
  428.     mov    wptr [mvhwFunctionTable+2],ax ; pointer in our code
  429.  
  430.     mov    es,ax            ; es:di points to the local table
  431.     mov    di,bx
  432.     mov    cx,10            ; update just ten entries
  433.     cld
  434.     ;
  435.     @@:
  436.     inc    di            ; pass the offset
  437.         inc     di
  438.     stosw                ; store the segment
  439.     loop    @B
  440.  
  441.     pop    di
  442.     pop    es
  443. ;
  444. ; setup a pointer to our local hardware state table
  445. ;
  446.     lea    bx,HardwareShadowTable
  447.     mov    wptr [mvhwShadowPointer+0],bx
  448.     mov    wptr [mvhwShadowPointer+2],cs
  449. ;
  450. ; find the int 2F interface
  451. ;
  452.     mov    ax,0bc00h        ; load the registers to check if
  453.     mov    bx,'??'                 ; MVSOUND.SYS is loaded.
  454.     sub    cx,cx            ; this is a unique enough approach
  455.     sub    dx,dx
  456.  
  457.         int     2fh                     ; get the response
  458.  
  459.         xor     bx,cx                   ; merge the response into BX
  460.     xor    bx,dx
  461.     cmp    bx,'MV'                 ; is the int 2F interface here?
  462.     jnz    inmv_done        ; no, exit home
  463. ;
  464. ; the int 2F interface is there, so get the state table.
  465. ;
  466.     mov    ax,0bc02h        ; get the state table pointer
  467.         int     2fh
  468.     mov    wptr [mvhwShadowPointer+0],bx
  469.     mov    wptr [mvhwShadowPointer+2],dx
  470.  
  471.     mov    ax,0bc03h        ; get the function pointer
  472.     int    2fh
  473.     mov    wptr [mvhwFunctionTable+0],bx
  474.     mov    wptr [mvhwFunctionTable+2],dx
  475.  
  476.         mov     ax,0bc04h               ; get the DMA and IRQ numbers
  477.     int    2fh
  478.     mov    TheDMAChannel,bl    ; save the correct DMA & IRQ
  479.     mov    TheIRQChannel,cl
  480. ;
  481. inmv_done:
  482.     mov    ax,wptr [mvhwFunctionTable+0]
  483.     mov    dx,wptr [mvhwFunctionTable+2]
  484.  
  485.         pop     ds
  486.     retf
  487.  
  488. doinit    endp
  489.  
  490. ;
  491. ;   /*\
  492. ;---|*|-------------------------===================-------------------------
  493. ;---|*|-----------------------====< dogetcross >====-------------------------
  494. ;---|*|-------------------------===================-------------------------
  495. ;---|*|
  496. ;---|*| Return the Cross channel mask
  497. ;---|*|
  498. ;---|*| Entry Conditions:
  499. ;---|*|     None
  500. ;---|*|
  501. ;---|*| Exit Conditions:
  502. ;---|*|     BX holds the old cross channel mask bits:
  503. ;---|*|
  504. ;---|*|     00000001b Right to Right
  505. ;---|*|     00000010b Right to Left
  506. ;---|*|     00000100b Left    to Right
  507. ;---|*|     00001000b Left    to Left
  508. ;---|*|
  509. ;---|*|     A set bit means the connection is ON.
  510. ;---|*|     A clear bit means the connection is OFF.
  511. ;---|*|
  512. ;   \*/
  513.  
  514.     public    dogetcross
  515. dogetcross    proc    far
  516.  
  517.     push    ax              ; save everything
  518.     push    cx
  519.     push    dx
  520.     push    ds
  521.  
  522.         push    es
  523.     push    di
  524.  
  525.     les    di,cs:[mvhwShadowPointer] ; get the pointer
  526.     mov    bl,es:[di._crosschannel]
  527.     and    bx,0000fh
  528.  
  529.         pop     di
  530.     pop    es
  531. ;
  532. far_return_less_bx    label    near
  533.     pop    ds
  534.     pop    dx
  535.     pop    cx
  536.     pop    ax
  537.     retf
  538.  
  539. dogetcross    endp
  540.  
  541. ;
  542. ;   /*\
  543. ;---|*|-------------------------===================-------------------------
  544. ;---|*|-----------------------====< dosetcross >====-------------------------
  545. ;---|*|-------------------------===================-------------------------
  546. ;---|*|
  547. ;---|*| Load a new cross channel mask
  548. ;---|*|
  549. ;---|*| Entry Conditions:
  550. ;---|*|     BX holds the new cross channel mask bits:
  551. ;---|*|
  552. ;---|*|     00000001b Right to Right
  553. ;---|*|     00000010b Right to Left
  554. ;---|*|     00000100b Left    to Right
  555. ;---|*|     00001000b Left    to Left
  556. ;---|*|
  557. ;---|*|     A set bit turns ON the connection.
  558. ;---|*|     A clear bit turns OFF the connection.
  559. ;---|*|
  560. ;---|*| Exit Conditions:
  561. ;---|*|     None
  562. ;---|*|
  563. ;   \*/
  564.  
  565.     public    dosetcross
  566. dosetcross      proc    far
  567.  
  568.         push    ax
  569.     push    bx
  570.     push    cx
  571.     push    dx
  572.     push    ds
  573.  
  574.         push    es
  575.     push    di
  576.     pushf
  577.  
  578.     les    di,cs:[mvhwShadowPointer]    ; get the pointer
  579.     mov    dx,CROSSCHANNEL
  580.     xchg    ax,bx
  581.  
  582.     cli                    ; kill ints until popf
  583.     mov    ah,es:[di._crosschannel]
  584.     and    ax,0f00fh
  585.     or    al,ah
  586.     mov    es:[di._crosschannel],al
  587.     out    dx,al
  588.  
  589.     popf
  590.         pop     di
  591.     pop    es
  592.  
  593.     jmp    far_return
  594.  
  595. dosetcross    endp
  596.  
  597. ;
  598. ;   /*\
  599. ;---|*|------------------------====================------------------------
  600. ;---|*|----------------------====< dogetfilter >====------------------------
  601. ;---|*|------------------------====================------------------------
  602. ;---|*|
  603. ;---|*| Return the current filter settings, from 0 to 100 %, where
  604. ;---|*| 0 is mute and 100 % is CD quality
  605. ;---|*|
  606. ;---|*| Entry Conditions:
  607. ;---|*|     None
  608. ;---|*|
  609. ;---|*| Exit Conditions:
  610. ;---|*|     BX holds the value
  611. ;---|*|
  612. ;   \*/
  613.  
  614.     public    dogetfilter
  615. dogetfilter    proc    far
  616.  
  617.         push    ax                      ; save everything
  618.     push    cx
  619.     push    dx
  620.     push    ds
  621.  
  622.         push    es
  623.     push    di
  624.     les    di,cs:[mvhwShadowPointer] ; get the pointer
  625.     mov    al,es:[di._audiofilt]
  626.         pop     di
  627.     pop    es
  628.  
  629.     sub    bx,bx            ; ax starts with mute
  630.     test    al,20h            ; mute bit clear
  631.     jz    dogefi_done        ; yes, we have the value
  632.  
  633.     mov    bx,17
  634.     cmp    al,24h            ; male voice?
  635.     jz    dogefi_done
  636.  
  637.     mov    bx,34
  638.     cmp    al,39h            ; Telephone?
  639.     jz    dogefi_done
  640.  
  641.     mov    bx,50
  642.     cmp    al,31h            ; AM Radio?
  643.     jz    dogefi_done
  644.  
  645.     mov    bx,67
  646.     cmp    al,29h            ; FM Radio?
  647.     jz    dogefi_done
  648.  
  649.     mov    bx,84
  650.     cmp    al,22h            ; Cassette?
  651.     jz    dogefi_done
  652.  
  653.     mov    bx,100            ; CD = 100 %
  654.  
  655. dogefi_done:
  656.     jmp    short far_return_less_bx
  657.  
  658. dogetfilter    endp
  659.  
  660. ;
  661. ;   /*\
  662. ;---|*|------------------------====================------------------------
  663. ;---|*|----------------------====< dosetfilter >====------------------------
  664. ;---|*|------------------------====================------------------------
  665. ;---|*|
  666. ;---|*| Set the filter to a setting from 0 to 100 %, where 0 is mute, 100 %
  667. ;---|*| is no filtering at all.
  668. ;---|*|
  669. ;---|*| Entry Conditions:
  670. ;---|*|     BX holds the value
  671. ;---|*|
  672. ;---|*| Exit Conditions:
  673. ;---|*|     None
  674. ;---|*|
  675. ;   \*/
  676.  
  677.     public    dosetfilter
  678. dosetfilter     proc    far
  679.     push    ax            ; save everything
  680.     push    bx
  681.     push    cx
  682.     push    dx
  683.     push    ds
  684.  
  685.         push    cs                      ; all data is stored locally.
  686.     pop    ds
  687.  
  688.     mov    ax,6            ; translate 0-100 % into 0-6
  689.     mov    bh,ah            ; flush the top half
  690.     xchg    ax,bx
  691.     or    ax,ax            ; if mute, skip the math...
  692.     jz    @F
  693.     mul    bx
  694.         mov     bl,100
  695.     div    bx            ; ax holds the new setting
  696. ;
  697. @@:
  698.         push    ax
  699.     call    SetFilter
  700.     pop    ax
  701.     jmp    far_return
  702.  
  703. dosetfilter       endp
  704.  
  705. ;
  706. ;   /*\
  707. ;---|*|------------------------===================------------------------
  708. ;---|*|----------------------====< dogetmixer >====------------------------
  709. ;---|*|------------------------===================------------------------
  710. ;---|*|
  711. ;---|*| Return the channel setting in either the input or output mixer.
  712. ;---|*| The return value will be 0 - 100 %
  713. ;---|*|
  714. ;---|*| Entry Conditions:
  715. ;---|*|     CX holds the mixer select (BI_OUTPUTMIXER or BI_INPUTMIXER)
  716. ;---|*|     DX holds the channel      (ex: L_LEFTFM, R_LEFTFM, etc.)
  717. ;---|*|
  718. ;---|*| Exit Conditions:
  719. ;---|*|     BX returns the volume     (0 - 100%)
  720. ;---|*|
  721. ;   \*/
  722.  
  723.     public    dogetmixer
  724. dogetmixer      proc    far
  725.     push    ax            ; save everything
  726.     push    cx
  727.     push    dx
  728.     push    ds
  729.  
  730.         push    cs                      ; all data is stored locally.
  731.     pop    ds
  732.  
  733.     mov    bx,dx
  734.         and     bx,0fh                  ; make sure the channel is legit
  735.     lea    ax,_inmixertbl
  736.     cmp    cx,BI_INPUTMIXER
  737.     jz    @F
  738.     lea    ax,_outmixertbl
  739.     ;
  740.     @@:
  741.     sub    cl,_currmixer[bx]    ; get the current channel selection
  742.         add     bx,ax
  743.     mov    al,[bx]         ; get the current value
  744.  
  745.         mov     bx,100                  ; translate 0-31 into 0-100%
  746.     cbw
  747.     mul    bx
  748.     or    ax,ax
  749.     jz    @F
  750.         mov     bl,31
  751.     div    bx            ; ax holds the new setting
  752.     ;
  753.     @@:
  754.     call    rounduppct        ; psuedo round up
  755.     xchg    ax,bx            ; bl holds the result
  756.     cmp    cl,1            ; carry set if Z, clear if NZ
  757.     sbb    bh,bh            ; bh holds the ON/OFF flag
  758.     jmp    far_return_less_bx
  759.  
  760. dogetmixer    endp
  761.  
  762. ;
  763. ;   /*\
  764. ;---|*|------------------------===================------------------------
  765. ;---|*|----------------------====< dosetmixer >====------------------------
  766. ;---|*|------------------------===================------------------------
  767. ;---|*|
  768. ;---|*| Set an input or output mixer channel from 0 to 100%
  769. ;---|*|
  770. ;---|*| Entry Conditions:
  771. ;---|*|     BX holds the volume       (0 - 100%)
  772. ;---|*|     CX holds the mixer select (BI_OUTPUTMIXER or BI_INPUTMIXER)
  773. ;---|*|     DX holds the channel      (ex: L_LEFTFM, R_LEFTFM, etc.)
  774. ;---|*|
  775. ;---|*| Exit Conditions:
  776. ;---|*|     None
  777. ;---|*|
  778. ;   \*/
  779.  
  780.     public    dosetmixer
  781. dosetmixer      proc    far
  782.  
  783.         push    ax                      ; save everything
  784.     push    bx
  785.     push    cx
  786.     push    dx
  787.     push    ds
  788.  
  789.         push    cs                      ; all data is stored locally.
  790.     pop    ds
  791. ;
  792. ; special case the variable channel assignments here...
  793. ;
  794.     cmp    cl,BI_L_SBDAC        ; if left SB
  795.     jnz    @F
  796.     mov    cl,[sbleft]        ; force it to be true
  797.     jmp    chgdone
  798.     ;
  799.     @@:
  800.     cmp    cl,BI_R_SBDAC        ; if right SB
  801.     jnz    @F
  802.     mov    cl,[sbright]        ; force it to be true
  803.     ;
  804.     chgdone:
  805. ;
  806. ; perform the mixer settings now...
  807. ;
  808.     push    dx            ; save the channels
  809.     push    dx            ; and one more copy
  810.  
  811.         mov     ax,31                   ; translate 0-100% into 0-31
  812.         mov     bh,ah                   ; flush the top half
  813.     xchg    ax,bx
  814.     or    ax,ax            ; if mute, skip the math...
  815.     jz    @F
  816.     mul    bx
  817.     mov    bl,100
  818.     div    bx            ; ax holds the new setting
  819. ;
  820. @@:
  821.     pop    bx            ; get the channel
  822.     and    bx,0fh            ; make sure the channel is legit
  823.  
  824.     lea    dx,_inmixertbl
  825.     mov    ch,INPUTMIXER
  826.     cmp    cl,BI_INPUTMIXER
  827.     jz    @F
  828.     lea    dx,_outmixertbl
  829.     mov    ch,OUTPUTMIXER
  830.     ;
  831.     @@:
  832.     mov    _currmixer[bx],cl    ; save the channel selection
  833.     add    bx,dx
  834.  
  835.     call    FetchMixLevel        ; on the National chip, convert to 0-12
  836.     mov    [bx],ax         ; save the new value
  837.  
  838.     xchg    ah,al            ; let ax hold the converted value
  839.     cbw
  840.  
  841.     mov    cl,ch            ; cl holds the parameter
  842.     mov    bx,ax            ; bx holds the channel setting
  843.     pop    ax            ; ax holds the channel #
  844.     call    SetMixer        ; set the mixer
  845. ;
  846. far_return      label   near            ; here for convienience sake
  847.     pop    ds
  848.         pop     dx
  849.     pop    cx
  850.     pop    bx
  851.     pop    ax
  852.     retf
  853.  
  854. dosetmixer    endp
  855.  
  856. ;
  857. ;   /*\
  858. ;---|*|------------------------====================------------------------
  859. ;---|*|----------------------====< dogetvolume >====------------------------
  860. ;---|*|------------------------====================------------------------
  861. ;---|*|
  862. ;---|*| Return with one of the volume register settings
  863. ;---|*|
  864. ;---|*| Entry Conditions:
  865. ;---|*|     CX holds the channel
  866. ;---|*|
  867. ;---|*| Exit Conditions:
  868. ;---|*|     BX holds the value
  869. ;---|*|
  870. ;   \*/
  871. ;
  872.     .errnz    VOLMUTE-40h            ; volume devices have bit 6 set
  873.     .errnz    BI_VOLENHANCE-BI_VOLLOUD-1  ; LOUDNESS=0, ENHANCED=1
  874.  
  875.     public    dogetvolume
  876. dogetvolume    proc    far
  877.  
  878.         push    ax                      ; save everything
  879.     push    cx
  880.     push    dx
  881.     push    ds
  882.  
  883.         push    cs                      ; all data is stored locally.
  884.     pop    ds
  885. ;
  886. ; convert the channel number to the table index
  887. ;
  888.     and    cx,07h            ; make it legit
  889.     mov    bx,cx            ; load the index into bx
  890.     cmp    cl,1            ; if it's BI_VOLLOUD, make it BI_VOLEHN...
  891.     sbb    ax,ax            ; ax = ffff if 0, 0000 if 1
  892.     adc    bl,0            ; if bl = 40, bl++
  893.     shl    bx,1            ; word indexing...
  894.  
  895.     mov    bx,[_voltbl+bx]     ; get the setting
  896. ;
  897. ; convert the volume settings into 0 - 100 % values
  898. ;
  899.     dec    cx            ; if 1, then it's loudness, enhanced
  900.     jle    dogvo_loudness        ; go do it...
  901.     mov    al,12
  902.     sub    cl,2            ; if LE,then it's BASS or TREBLE scale
  903.     jle    dogvo_scale
  904.         mov     al,40
  905. ;
  906. ; volume or equalizer settings
  907. ;
  908.     dogvo_scale:
  909.     xchg    ax,bx            ; ax = the current setting, bx the max
  910.     or    ax,ax
  911.     jz    dogvo_done
  912.     mov    cx,100
  913.     mul    cx
  914.     div    bx
  915.     jmp    short dogvo_done
  916. ;
  917. ; loudness and enhanced buttons
  918. ;
  919.     dogvo_loudness:
  920.     not    ax
  921.     and    al,1            ; al = 0 for volloud, 1 for enhanced
  922.     inc    al            ; al = 1 for volloud, 2 for enhanced
  923.  
  924.     and    al,bl            ; al holds the bit
  925.     neg    al            ; set carry on zero
  926.     sbb    al,al
  927.     and    ax,100            ; ax = 0 for off, 100 for on
  928. ;
  929. dogvo_done:
  930.     call    rounduppct        ; psuedo rounding
  931.     xchg    ax,bx            ; bx holds the result
  932.     jmp    far_return_less_bx
  933.  
  934. dogetvolume    endp
  935.  
  936. ;
  937. ;   /*\
  938. ;---|*|------------------------====================------------------------
  939. ;---|*|----------------------====< dosetvolume >====------------------------
  940. ;---|*|------------------------====================------------------------
  941. ;---|*|
  942. ;---|*| Set one of the volume register with stufff...
  943. ;---|*|
  944. ;---|*| Entry Conditions:
  945. ;---|*|     BX holds the value
  946. ;---|*|     CX holds the channel
  947. ;---|*|
  948. ;---|*| Exit Conditions:
  949. ;---|*|     None
  950. ;---|*|
  951. ;   \*/
  952. ;
  953.     .errnz    VOLMUTE-40h            ; volume devices have bit 6 set
  954.     .errnz    BI_VOLENHANCE-BI_VOLLOUD-1  ; LOUDNESS=0, ENHANCED=1
  955.  
  956.     public    dosetvolume
  957. dosetvolume     proc    far
  958.  
  959.         push    ax                      ; save everything
  960.     push    bx
  961.     push    cx
  962.     push    dx
  963.     push    ds
  964.  
  965.         push    cs                      ; all data is stored locally.
  966.     pop    ds
  967.  
  968.         sub     bh,bh                   ; make sure its a low value
  969. ;
  970. ; convert the channel number to something close
  971. ;
  972.     or    cl,40h            ; add in the National device select bit
  973. ;
  974. ; volume settings
  975. ;
  976.     cmp    cl,BI_VOLLEFT+40H
  977.     jz    dovo_volume
  978.     cmp    cl,BI_VOLRIGHT+40H
  979.     jnz    dovo_notvolume
  980.     ;
  981.     dovo_volume:
  982.     mov    al,[_volleftmax]    ; xlat 0-100% to the physical max
  983.     cbw
  984.     xchg    ax,bx
  985.     or    ax,ax
  986.     jz    dovo_sendit
  987.     mul    bx
  988.     mov    bl,100
  989.     div    bx
  990.     jmp    short dovo_sendit
  991. ;
  992. dovo_notvolume:
  993. ;
  994. ; bass/treble settings
  995. ;
  996.     cmp    cl,BI_VOLBASS+40H
  997.     jz    dovo_bass
  998.     cmp    cl,BI_VOLTREBLE+40H
  999.     jnz    dovo_not_basstreble
  1000.     ;
  1001.     dovo_bass:
  1002.     mov    ax,12            ; xlat 0-100% to 0-12
  1003.     xchg    ax,bx
  1004.     or    ax,ax
  1005.     jz    dovo_sendit
  1006.     mul    bx
  1007.     mov    bl,100
  1008.     div    bx
  1009.     jmp    short dovo_sendit
  1010. ;
  1011. dovo_not_basstreble:
  1012. ;
  1013. ; loudness and enhanced buttons
  1014. ;
  1015.     mov    ax,0fe01h        ; load a mask for stripping/saving bits
  1016.     cmp    cl,BI_VOLLOUD+40H    ; loudness?
  1017.     jz    dovo_loudness        ; yes, use it
  1018.     cmp    cl,BI_VOLENHANCE+40H    ; enhanced?
  1019.     jnz    dovo_bad        ; no, bomb out...
  1020.     mov    ax,0fd02h        ; load a mask for stripping/saving bits
  1021.     ;
  1022.     dovo_loudness:
  1023.  
  1024.         or      cl,01                   ; calc the true volume register
  1025.     .errnz    (VOLLOUDENH AND 0BFh) - 1 ; make sure the above ADD works
  1026.  
  1027.     and    ah,byte ptr [_voltbl+2]     ; get all other bits
  1028.     .errnz    VOLLOUDENH-41h        ; must be entry #2
  1029.  
  1030.     neg    bl            ; sets carry if not zero
  1031.     sbb    bl,bl            ; bl = 0000 if 0, else ffff for 1
  1032.     and    al,bl
  1033.     or    al,ah            ; al holds the new value
  1034. ;
  1035. dovo_sendit:
  1036.     sub    ch,ch            ; guarrenteed goodness...
  1037.     sub    ah,ah            ; guarrenteed goodness...
  1038.     mov    bx,cx            ; bx holds the channel, ax the value
  1039.     xchg    ax,bx            ; for keeping the parameters straight...
  1040.         call    SetVolume
  1041. ;
  1042. dovo_bad:
  1043.     jmp    far_return
  1044.  
  1045. dosetvolume    endp
  1046.  
  1047. ;
  1048. ;   /*\
  1049. ;---|*|------------------===============================-----------------------
  1050. ;---|*|----------------====< dorealsound/dofmsplit >======---------------------
  1051. ;---|*|------------------===============================-----------------------
  1052. ;---|*|
  1053. ;---|*| Set/Get the realsound and FM bit settings
  1054. ;---|*|
  1055. ;---|*| Entry Conditions:
  1056. ;---|*|     BX holds the 0 for off, ~0 for ON
  1057. ;---|*|     CX holds 0 to get, 1 to set the bit
  1058. ;---|*|
  1059. ;---|*| Exit Conditions:
  1060. ;---|*|     BX may return the value
  1061. ;---|*|
  1062. ;   \*/
  1063. ;
  1064.     public    dorealsound
  1065. dorealsound     proc    far
  1066.  
  1067.         push    ax                      ; save everything
  1068.     push    cx
  1069.     push    dx
  1070.     push    ds
  1071.  
  1072.     mov    ah,bMIspkrint        ; realsound bit
  1073.  
  1074.         push    cs                      ; all data is stored locally.
  1075.     pop    ds
  1076.  
  1077.     push    es
  1078.     push    di
  1079.     les    di,mvhwShadowPointer    ; get the pointer
  1080. ;
  1081. finish_common_code:
  1082.     jcxz    dogetrealorfm        ; if not set, go get the bit
  1083.  
  1084.     push    bx            ; since this is a SET we can't flush bx
  1085. ;
  1086. ; create an AND / OR mask to set/clear the bit
  1087. ;
  1088.     neg    bx            ; set carry if nonzero
  1089.     sbb    al,al            ; al = 0000 for 0, ffff for 1
  1090.     and    al,ah            ; al holds the OR bit mask
  1091.     not    ah            ; ah holds the AND bit mask
  1092.  
  1093.         mov     dx,AUDIOMIXR
  1094.  
  1095.         pushf
  1096.     cli
  1097.  
  1098.     and    ah,es:[di._audiomixr]    ; get all but the realsound/fm bit
  1099.  
  1100.         or      al,ah                   ; merge into the one bit
  1101.  
  1102.     out    dx,al
  1103.     mov    es:[di._audiomixr],al    ; save the new bit
  1104.  
  1105.     popf
  1106.     pop    bx                 ; restore bx
  1107.     jmp    short dogetrealdone
  1108.     ;
  1109.     dogetrealorfm:
  1110.  
  1111.     and    ah,es:[di._audiomixr]    ; get the bit
  1112.     neg    ah            ; carry set if nonzero
  1113.     sbb    bx,bx            ; bx = ffff for ~0, 0000 for 0
  1114.     and    bx,100            ; bx = 0 or 100%
  1115.     ;
  1116.     dogetrealdone:
  1117.     pop    di
  1118.     pop    es
  1119.     jmp    far_return_less_bx
  1120.  
  1121. ;
  1122. ;----====< dofmsplit entrypoint >====----
  1123. ;
  1124.  
  1125. dofmsplit    label far
  1126.     push    ax            ; save everything
  1127.     push    cx
  1128.     push    dx
  1129.     push    ds
  1130.  
  1131.     mov    ah,bMImonofm        ; fm bit
  1132.  
  1133.         push    cs                      ; all data is stored locally.
  1134.     pop    ds
  1135. ;
  1136. ; check the different hardware versions.
  1137. ;
  1138.     push    es
  1139.     push    di
  1140.     les    di,mvhwShadowPointer    ; get the pointer
  1141.  
  1142.     test    es:[di._intrctlr],fICidbits ; rev 2+ ?
  1143.     jz    finish_common_code        ; no, handle as PAS1
  1144.     jcxz    finish_common_code        ; also, GETs will go that way...
  1145. ;
  1146. ; OPL3 board, so do the switch at the OPL3 chip
  1147. ;
  1148.     mov    ax,bx            ; save BX
  1149.     neg    ax            ; set carry to turn off
  1150.     sbb    ax,ax            ; al = 0 for OFF, FF for ON
  1151.     and    ah,1            ; ah = 0 for OFF, 01 for ON
  1152.     xor    ah,1            ; flip for the OPL 3
  1153. ;
  1154. ; maintain compatibility with the old mixer setup.
  1155. ;
  1156.     and    al,bMImonofm        ; save just that bit
  1157.  
  1158.     and    es:[di._audiomixr],NOT bMImonofm ; flush the bit
  1159.     or    es:[di._audiomixr],al         ; maybe set the bit
  1160.  
  1161.     mov    al,05h
  1162.     mov    dx,RFMADDR        ; write to the new bit in the OPL3
  1163.     out    dx,al            ; index first...
  1164.     inc    dx
  1165.  
  1166.         in      al,dx                   ; waste time...
  1167.         in      al,dx                   ; waste time...
  1168.  
  1169.     mov    al,ah            ; data next...
  1170.     out    dx,al
  1171.  
  1172.     jmp    short dogetrealdone    ; exit via common code
  1173.  
  1174. dorealsound     endp
  1175.  
  1176. ;
  1177. ;   /*\
  1178. ;---|*|----====< int SetCrossChannel >====----
  1179. ;---|*|
  1180. ;---|*| Output New Cross Channel Select Bits
  1181. ;---|*|
  1182. ;---|*| Entry Conditions:
  1183. ;---|*|     AX holds the channel bit
  1184. ;---|*|     DX holds the state (0 or -1)
  1185. ;---|*|     DS holds our data segment
  1186. ;---|*|
  1187. ;---|*| Exit Conditions:
  1188. ;---|*|     AX,DX modified.
  1189. ;---|*|     h/w channel select modified
  1190. ;---|*|
  1191. ;   \*/
  1192.  
  1193.     public    SetCrossChannel
  1194. SetCrossChannel proc
  1195.     push    es
  1196.     push    di
  1197.     les    di,mvhwShadowPointer    ; get the pointer
  1198.  
  1199.         mov     ah,al                   ; ah = AND mask al = XOR mask
  1200.     not    ah
  1201.     and    al,dl            ; al = 00 to clear, else 0X to set
  1202.  
  1203.         mov     dx,CROSSCHANNEL
  1204.  
  1205.     disable
  1206.  
  1207.     and    ah,es:[di._crosschannel]
  1208.     xor    al,ah
  1209.     out    dx,al
  1210.     mov    es:[di._crosschannel],al ; save the new value, & return the old
  1211.  
  1212.         enable
  1213.  
  1214.     pop    di
  1215.     pop    es
  1216.     ret
  1217.  
  1218. SetCrossChannel endp
  1219.  
  1220. ;
  1221. ;   /*\
  1222. ;---|*|----====< void SetFilter (int setting ) >===----
  1223. ;---|*|
  1224. ;---|*|       This routine selects a filter setting from mute to high freq filter.
  1225. ;---|*|
  1226. ;---|*| Entry Conditions:
  1227. ;---|*|     AX is a value from 0 - 6
  1228. ;---|*|     DS holds our data segment
  1229. ;---|*|
  1230. ;---|*| Exit Conditions:
  1231. ;---|*|     None
  1232. ;---|*|
  1233. ;---|*|
  1234. ;   \*/
  1235.  
  1236.     public    SetFilter
  1237. SetFilter       proc
  1238.     push    es
  1239.     push    di
  1240.     les    di,mvhwShadowPointer    ; get the pointer
  1241.  
  1242.         mov     bx,ax
  1243.     cmp    bx,6            ; validate the user index
  1244.     ja    sfbadval
  1245.  
  1246.     mov    _filtidx,bl
  1247.     mov    ah,tableof[bx]        ; grab an appropriate value
  1248.     mov    dx,AUDIOFILT        ; and toss it out...
  1249.  
  1250.     disable
  1251.  
  1252.     mov    al,es:[di._audiofilt]    ; get the shadowed gates
  1253.  
  1254.         and     al,not (fFIdatabits+fFImutebits) ; save the non-filter bits
  1255.     or    al,ah            ; merge in the filter bits
  1256.         out     dx,al
  1257.  
  1258.     mov    es:[di._audiofilt],al    ; shadow it too...
  1259.  
  1260.         enable
  1261. ;
  1262. sfbadval:
  1263.     pop    di
  1264.     pop    es
  1265.         ret
  1266.  
  1267. SetFilter    endp
  1268.  
  1269. ;
  1270. ;   /*\
  1271. ;---|*|----====< void SetMixer >====----
  1272. ;---|*|
  1273. ;---|*| Set the selected channel within the MVA508 Mixers & Volume device
  1274. ;---|*|
  1275. ;---|*| Entry Conditions:
  1276. ;---|*|     AX holds the channel (0 - 15)
  1277. ;---|*|     BX holds the volume  (0 - 31)
  1278. ;---|*|     CL holds the device: OUTPUTMIXER or INPUTMIXER or DEFMIXER
  1279. ;---|*|     DS holds our data segment
  1280. ;---|*|
  1281. ;---|*| Exit Conditions:
  1282. ;---|*|     AX,BX,CX,DX modified
  1283. ;---|*|
  1284. ;   \*/
  1285.  
  1286.     public    SetMixer
  1287. SetMixer        proc    near
  1288.     push    es
  1289.     push    di
  1290.     les    di,mvhwShadowPointer    ; get the pointer
  1291.  
  1292.         xchg    bx,ax                   ; bx = channel #, al = volume
  1293.         mov     ah,al                   ; ah = real, al = simulated
  1294.  
  1295.         test    [hardwaretype],bMVA508
  1296.     jjz    nsSetMixer
  1297.     ;
  1298.     ; we scale down the mixer settings to make them
  1299.     ; sound more like the National part.
  1300.     ;
  1301.         mov     ch,ah                   ; multiply the value by 1.25  We take
  1302.     shr    ch,1            ; the value, divide in half, then
  1303.         shr     ch,1                    ; the value, divide in half, then
  1304.     add    ah,ch            ; add it back in.
  1305.     cmp    ah,1Fh            ; not maxed out, just use it...
  1306.         jbe     @F
  1307.     mov    ah,1Fh            ; max it out...
  1308.     ;
  1309.     @@:
  1310. ;
  1311. ; send out the mixer channel #
  1312. ;
  1313.     mov    al,cs:mv508table[bx]    ; get the true mixer channel
  1314.     mov    dx,pAUDIOMIXR        ; parallel mixer address
  1315.  
  1316.         push    ax
  1317.  
  1318.         dec     dx
  1319.     mov    ah,al
  1320.     out    dx,ax
  1321. ;
  1322. ; convert the mixer select from the National definition to the MVA508
  1323. ;
  1324.     .errnz    OUTPUTMIXER        ; must always be zero
  1325.     .erre    INPUTMIXER        ; must always be non-zero
  1326.     .erre    pmINPUTMIXER        ; must always be non-zero
  1327.  
  1328.     pop    ax
  1329.         neg     cl                      ; CY if INPUT mixer, NC for OUTPUT mixer
  1330.     sbb    al,al
  1331.     and    al,pmINPUTMIXER     ; al now holds the proper bit field
  1332.     or    al,ah            ; real mixer channel volume level
  1333.     mov    ah,al
  1334.     out    dx,ax
  1335.  
  1336.     mov    es:[di._paudiomixr],al    ; shadow it...
  1337. ;
  1338. semi_exit:
  1339.     pop    di
  1340.     pop    es
  1341.         ret
  1342. ;
  1343. ; National Semi Mixer setting code
  1344. ;
  1345. nsSetMixer:
  1346.     push    ax            ; save the channel setting
  1347.     push    cx            ; save the INPUTMIXER/OUTPUTMIXER bits
  1348. ;
  1349. ; send out the mixer channel #
  1350. ;
  1351.     test    cs:[hardwaretype],CDPC    ; CDPC mixer L/R connections are
  1352.     jz    @F            ; backwards...
  1353.     mov    bl,cs:[cdpcmixer+bx]    ; We will straighten them out.
  1354.     @@:
  1355.     mov    ah,bl            ; restore the register #
  1356.     or    ah,080h         ; OR 080h  d7=channel #
  1357.     or    ah,cl            ; merge in the mixer select
  1358.         call    lmix                    ;  (lvol looks for 80h)
  1359. ;
  1360. ; send out the mixer data
  1361. ;
  1362.     pop    cx            ; get the INPUTMIXER/OUTPUTMIXER
  1363.     pop    ax            ; get the channel setting in AH
  1364.         or      ah,cl                   ; merge in the mixer select
  1365.         call    lmix
  1366. ;
  1367. _semi_exit:
  1368.     pop    di
  1369.     pop    es
  1370.     ret
  1371. ;
  1372. ; This table reverses the mixer settings so left is now right & visa versa.
  1373. ;
  1374. cdpcmixer       label   byte
  1375.     db    15            ;  nothing
  1376.     db    08            ; Left FM
  1377.     db    09            ; Left input mixer
  1378.     db    10            ; Left External
  1379.     db    11            ; Left Internal
  1380.     db    12            ; Left Mic
  1381.     db    13            ; Left PCM
  1382.     db    14            ; Left Speaker
  1383.  
  1384.     db    0            ;  nothing
  1385.     db    01            ; Right FM
  1386.     db    02            ; Right Input Mixer
  1387.     db    03            ; Right External
  1388.     db    04            ; Right Internal
  1389.     db    05            ; Right Mic
  1390.     db    06            ; Right PCM
  1391.     db    07            ; Right Speaker
  1392.  
  1393. pmADMI    equ    <pmADDRSELECT+pmMIXERSELECT>
  1394.  
  1395. mv508table    label    byte        ;Ch #; PAS   ; MVA508
  1396.     db    07+pmCHANNELL+pmADMI    ;  0 ; L_FREE;    7 - Now the SB connect
  1397.     db    00+pmCHANNELL+pmADMI    ;  1 ; L_FM  ;    0
  1398.     db    01+pmCHANNELL+pmADMI    ;  2 ; L_Mix ;    1
  1399.     db    02+pmCHANNELL+pmADMI    ;  3 ; L_Ext ;    2
  1400.     db    03+pmCHANNELL+pmADMI    ;  4 ; L_Int ;    4
  1401.     db    04+pmCHANNELL+pmADMI    ;  5 ; L_Mic ;    3
  1402.     db    05+pmCHANNELL+pmADMI    ;  6 ; L_PCM ;    5
  1403.     db    06+pmCHANNELL+pmADMI    ;  7 ; L_Spk ;    6
  1404.     db    00+pmCHANNELR+pmADMI    ;  8 ; R_FM  ;    0
  1405.     db    01+pmCHANNELR+pmADMI    ;  9 ; R_Mix ;    1
  1406.     db    02+pmCHANNELR+pmADMI    ;  A ; R_Ext ;    2
  1407.     db    03+pmCHANNELR+pmADMI    ;  B ; R_Int ;    4
  1408.     db    04+pmCHANNELR+pmADMI    ;  C ; R_Mic ;    3
  1409.     db    05+pmCHANNELR+pmADMI    ;  D ; R_PCM ;    5
  1410.     db    06+pmCHANNELR+pmADMI    ;  E ; R_Spk ;    6
  1411.     db    07+pmCHANNELR+pmADMI    ;  F ; R_FREE;    7 - Now the SB connect
  1412.  
  1413. SetMixer    endp
  1414.  
  1415. ;
  1416. ;   /*\
  1417. ;---|*|----====< void SetVolume >====----
  1418. ;---|*|
  1419. ;---|*|       This routine outputs a new setting for a volume channel.
  1420. ;---|*|
  1421. ;---|*| Entry Conditions:
  1422. ;---|*|     AX is a register select value from 0 - 7
  1423. ;---|*|     BX is a value to be written to the control
  1424. ;---|*|     DS points to our data segment
  1425. ;---|*|
  1426. ;---|*| Exit Conditions:
  1427. ;---|*|     AX,BX,CX,DX may be modified
  1428. ;---|*|
  1429. ;   \*/
  1430.  
  1431.     public    SetVolume
  1432. SetVolume       proc
  1433.     push    es
  1434.     push    di
  1435.     les    di,mvhwShadowPointer    ; get the pointer
  1436.  
  1437.     test    [hardwaretype],bMVA508
  1438.     jjz    _nsSetVolume
  1439.  
  1440.         xchg    ax,bx                   ; ax = data, bx = channel
  1441.  
  1442.         and     bl,10111111b            ; knock out the Volume ID bit
  1443.  
  1444.         shl     bx,1
  1445.         mov     _voltbl[bx],ax          ; save this channel's volume setting
  1446.     shr    bx,1            ; restore bx & go
  1447.  
  1448.         mov     ah,cs:mva508vol[bx]     ; get the channel number for the MVA508
  1449.     xchg    ah,al            ; al = channel, ah = data
  1450.     cmp    al,-1            ; is there an actual channel?
  1451.     jz    sevo_exit        ; no, just skip it...
  1452.     ;
  1453.     ; special case the loudness and enhanced stereo switches for the MVA508
  1454.     ;
  1455.     cmp    bl,VOLLOUDENH AND 7    ; volume enhance switches?
  1456.     jnz    @F            ; no, continue on...
  1457.     shr    ah,1            ; yes, swap the bit positions
  1458.     sbb    dl,dl
  1459.     and    dl,2
  1460.     or    ah,dl
  1461.     shl    ah,1
  1462.     ;
  1463.     @@:
  1464.         mov     dx,pAUDIOMIXR           ; parallel audio mixer interface
  1465.     dec    dx
  1466.  
  1467.     push    ax
  1468.     mov    ah,al
  1469.     out    dx,ax            ; write the index
  1470.     pop    ax
  1471.  
  1472.         xchg    ah,al                   ; al = data, ah = channel
  1473.     mov    ah,al
  1474.     out    dx,ax            ; write the data
  1475.  
  1476.         mov     es:[di._paudiomixr],al  ; shadow it...
  1477. ;
  1478. sevo_exit:
  1479.     pop    di
  1480.     pop    es
  1481.         ret
  1482. ;
  1483. ; National Semi's total volume control
  1484. ;
  1485. _nsSetVolume:
  1486.     xchg    ax,bx            ; ax = data, bx = channel
  1487.  
  1488.         and     bl,10111111b            ; knock out the Volume ID bit
  1489.     shl    bx,1
  1490.  
  1491.         mov     _voltbl[bx],ax          ; save this channel's volume setting
  1492.  
  1493.     shr    bx,1            ; restore bx & go
  1494.     or    bl,01000000b        ; replace the Volume ID bit
  1495.     mov    ah,al            ; ah = data
  1496.     call    lvol            ; call the read hardware routine
  1497.  
  1498.         jmp     short sevo_exit
  1499.  
  1500. ;
  1501. ; MVA580 mixer channel assignments
  1502. ;
  1503. mva508vol    label    byte           ; ch #  ;  PAS     ; MVA508
  1504.     db    02+pmADDRSELECT+pmCHANNELLR;  0    ; MUTE     ;  VOLB
  1505.     db    05+pmADDRSELECT        ;  1    ; LOUD/ENH ;   5
  1506.     db    03+pmADDRSELECT        ;  2    ; BASS     ;   3
  1507.     db    04+pmADDRSELECT        ;  3    ; TREBLE   ;   4
  1508.     db    01+pmADDRSELECT+pmCHANNELL ;  4    ; L-VOL    ;   1,CC=01
  1509.     db    01+pmADDRSELECT+pmCHANNELR ;  5    ; R-VOl    ;   1,CC=02
  1510.     db    -1               ;  6    ; MODE     ;  N/A
  1511.     db    -1               ;  7    ; N/A      ;  N/A
  1512.  
  1513. SetVolume       endp
  1514.  
  1515. ;
  1516. ;---------------------====================================---------------------
  1517. ;---------------------====< Local Subroutine Section >====---------------------
  1518. ;---------------------====================================---------------------
  1519. ;
  1520.  
  1521. ;   /*\
  1522. ;---|*|----====< FetchMixLevel >====----
  1523. ;---|*|
  1524. ;---|*| Remap mixer level from 0-31 into 0-12
  1525. ;---|*|
  1526. ;---|*| Entry Conditions:
  1527. ;---|*|     AX holds the volume level - guarrenteed to be 0 - 31
  1528. ;---|*|     DS holds our data segment
  1529. ;---|*|
  1530. ;---|*| Exit Condtions:
  1531. ;---|*|     CY = 1, invalid volume level.
  1532. ;---|*|     CY = 0, good volume level.
  1533. ;---|*|      AH holds the converted value.
  1534. ;---|*|      AL the orig index.
  1535. ;---|*|
  1536. ;   \*/
  1537.  
  1538.     public    FetchMixLevel
  1539. FetchMixLevel   proc    near
  1540. ;
  1541. ; ignore if the new mixer
  1542. ;
  1543.     mov    ah,al            ; ah may return the whole thing
  1544.     test    [HardwareType],bMVA508    ; if this is the MVA508
  1545.     jnz    @F
  1546. ;
  1547. ; do the converion for the old mixer
  1548. ;
  1549.         push    bx
  1550.     push    dx
  1551.     push    ax
  1552. ;
  1553. ; remap 0-31 into 0-12: index = (index * 10) / 2.5
  1554. ;
  1555.     mov    dl,10
  1556.     mul    dl
  1557.     mov    dl,25
  1558.     div    dl            ; effectely divides 31 by 2.5
  1559. ;
  1560. ; read the table of hosed values
  1561. ;
  1562.     mov    bl,al
  1563.     sub    bh,bh
  1564.  
  1565.     pop    ax            ; al holds the original index
  1566.     mov    ah,mixersettings[bx]    ; ah holds the real setting
  1567.  
  1568.     pop    dx
  1569.     pop    bx
  1570. ;
  1571. @@:
  1572.     clc
  1573.         ret
  1574.  
  1575. FetchMixLevel    endp
  1576.  
  1577.  
  1578. ;   /*\
  1579. ;---|*|----====< lmix >====----
  1580. ;   \*/
  1581.  
  1582. ;
  1583. ; -- Load The Mixer
  1584. ;
  1585. ; Entry Conditions
  1586. ;    es:di point to the state table
  1587. ;    ah = index/data
  1588. ;    al = to mixer:
  1589. ;        al = INPUTMIXER  (04h) - goes to input mixer
  1590. ;        al = OUTPUTMIXER (08h) - goes to output mixer
  1591. ;
  1592. ; Exit Conditions:
  1593. ;    No registers modified
  1594. ;
  1595.     public    lmix
  1596. lmix    proc    near
  1597.     push    ax
  1598.     push    cx
  1599.     push    dx
  1600.  
  1601.     disable             ; make sure we clock in all data
  1602. ;
  1603. ; all clocks and ; strobes should be 1
  1604. ;
  1605.     mov    dx,AUDIOMIXR        ; load mixer port
  1606.  
  1607.         mov     al,es:[di._audiomixr]   ; save the realsound & dual fm bits
  1608.  
  1609.         and     al,bMIspkrint+bMImonofm
  1610.     or    al,not (bMIspkrint+bMImonofm)
  1611.  
  1612.         mov     cx,8                    ; load bit count
  1613.     out    dx,al            ; set initial clocks
  1614.  
  1615. @@:    xor    al,bMIclock        ; toggle output mixer clock
  1616.         pause
  1617.     out    dx,al            ; output clock is zero
  1618.     ror    al,1            ; make room for data
  1619.     ror    ah,1            ; get bit of data
  1620.     adc    al,al            ; shift into register
  1621.     out    dx,al            ; send data to mixer
  1622.     xor    al,bMIclock        ; toggle clock again
  1623.         pause
  1624.     out    dx,al            ; clock sould be 1 now
  1625.     loop    @B            ; do all 8 bits this way
  1626.  
  1627.         xor     al,bMImistrb            ; toggle strobe low
  1628.     out    dx,al            ; which loads data into mixer
  1629.     pause
  1630.     xor    al,bMImistrb        ; toggle strobe high
  1631.     out    dx,al            ; loading complete
  1632.  
  1633.     mov    es:[di._audiomixr],al    ; save the last state
  1634.  
  1635.         enable
  1636.  
  1637.     pop    dx
  1638.     pop    cx
  1639.     pop    ax
  1640.         ret
  1641.  
  1642. lmix    endp
  1643.  
  1644. ;
  1645. ;   /*\
  1646. ;---|*|----====< lvol >====----
  1647. ;   \*/
  1648.  
  1649. ;
  1650. ; lvol    -- Load Volume control Register
  1651. ;
  1652. ; Entry Conditions:
  1653. ;    bl = parameter register (volume control channel 0-7)
  1654. ;    ah = data to transfer    (new channel setting)
  1655. ;
  1656. ; Exit Conditions:
  1657. ;    AX,BX,CX,DX modified
  1658. ;
  1659.     public    lvol
  1660. lvol    proc    near
  1661. ;
  1662. ; pass everything, but left/right volume directly to the device
  1663. ;
  1664.     cmp    bl,44h            ; left & right volume are presented
  1665.     jz    @F            ; to the logical level as 0 - 40,
  1666.     cmp    bl,45h            ; where 0 is the lowest, and 40 is
  1667.     jnz    lvolout         ; the highest. In reality, this
  1668. @@:    sub    ah,40            ; is backwards, that is, 40 is the
  1669.     neg    ah            ; lowest, and 0 is the highest. We will
  1670. ;                    ; correct the value here...
  1671. ; Perform the volume control output
  1672. ;
  1673. lvolout label    near
  1674.     mov    dx,AUDIOMIXR        ; load mixer port
  1675. ;
  1676. ; all 1s but volume enable and clock
  1677. ;
  1678.     mov    al,es:[di._audiomixr]    ; save the realsound & dual fm bits
  1679.  
  1680.         and     al,bMIspkrint+bMImonofm
  1681.     or    al,not (bMIspkrint+bMImonofm+bMIvol+bMIclock)
  1682.  
  1683.     disable             ; do it all at once, no interruptions
  1684.  
  1685.         out     dx,al                   ; set initial clocks
  1686.     mov    cx,8            ; load bit count for address
  1687. @@:    xor    al,bMIclock        ; toggle volume control clock
  1688.     ror    al,1            ; make room for data
  1689.     ror    bl,1            ; get bit of data
  1690.     adc    al,al            ; shift into register
  1691.     out    dx,al            ; send data to volume control
  1692.     pause
  1693.         xor     al,bMIclock             ; toggle the clock again
  1694.     out    dx,al            ; clock should be 1 now
  1695.     loop    @B            ; do all 8 bits this way...
  1696.     xor    al,bMIvol        ; toggle volume control enable
  1697.         pause
  1698.     out    dx,al            ; which starts data loading
  1699.     mov    cl,8            ; load bit count for data
  1700. @@:    xor    al,bMIclock        ; toggle volume control clock
  1701.     ror    al,1            ; make room for data
  1702.     ror    ah,1            ; get bit of data
  1703.     adc    al,al            ; shift into register
  1704.     out    dx,al            ; send data to volume control
  1705.         pause
  1706.     xor    al,bMIclock        ; toggle clock again
  1707.     out    dx,al            ; clock should be 1 now
  1708.     loop    @B            ; doall a 8 bits this way...
  1709.         pause
  1710.     mov    cl,12            ; load bit count for data
  1711. @@:    out    dx,al            ; need to stall for 6 microseconds
  1712.         pause
  1713.     loop    @B            ; waiting...
  1714.     xor    al,bMIvol        ; toggle volume control enable
  1715.     out    dx,al            ; to prepare
  1716.         pause
  1717.     out    dx,al            ; need to stall
  1718.         pause
  1719.     out    dx,al
  1720.         pause
  1721.     out    dx,al
  1722.         pause
  1723.     xor    al,bMIvol        ; toggle volume control enable
  1724.     out    dx,al            ; which loads data
  1725.  
  1726.     mov    es:[di._audiomixr],al    ; save the last state
  1727.  
  1728.         enable
  1729.  
  1730.         ret
  1731.  
  1732. lvol    endp
  1733.  
  1734. ;
  1735. ;----====< rounduppct >====----
  1736. ;
  1737. rounduppct    proc    near
  1738.     cmp    al,0            ; skip out if less than zero
  1739.     jle    @F
  1740.     cmp    al,100            ; skip out if greater/equal to 100
  1741.     jge    @F
  1742.     inc    al
  1743. ;
  1744. @@:
  1745.     ret
  1746.  
  1747. rounduppct    endp
  1748.  
  1749.  
  1750. ;   /*\
  1751. ;---|*|----====< end of MIXERS.ASM >====----
  1752. ;   \*/
  1753.  
  1754.     end
  1755.  
  1756.